// **************************************************************
// COPYRIGHT(c)2020, Xidian University
// All rights reserved.
//
// IP LIB INDEX :  
// IP Name      :      
// File name    : 
// Module name  : 
// Full name    :  
//
// Author       : Hbing
// Email        : 2629029232@qq.com
// Data         : 2020/8/29
// Version      : V 1.0 
// 
// Abstract     : 
// Called by    :  
// 
// Modification history
// -----------------------------------------------------------------
// V1.0 完成基础功能，严格优先级调度
// V2.0 支持三种调度策略,DWRR,SP,RR
// 
// *****************************************************************
`include "top_define.v"
// *******************
// TIMESCALE
// ******************* 
`timescale 1ns/1ps 

// *******************
// DESCRIPTION
// *******************
// 3*3交叉节点，但是为了防止阻塞，第三列交叉节点中的乒乓RAM翻倍，分别存port2,port3目的端口的数据帧
// 暂时按照严格优先级调度，之后可以改进为DWRR策略
// 
//*******************
//DEFINE(s)
//*******************
//`define UDLY 1    //Unit delay, for non-blocking assignments in sequential logic

//*******************
//DEFINE MODULE PORT
//*******************
 module bus_master_tx(
    //sysrem input/output
    input  wire         clk  ,
    input  wire         rst_n,
    //新增CPU配置DWRR权重以及开启使能
    input  wire [ 15:0] weight_back_num,
    input  wire         DWRR_en,
    input  wire [ 15:0] WEIGHT7,
    input  wire [ 15:0] WEIGHT6,
    input  wire [ 15:0] WEIGHT5,
    input  wire [ 15:0] WEIGHT4,
    input  wire [ 15:0] WEIGHT3,
    input  wire [ 15:0] WEIGHT2,
    input  wire [ 15:0] WEIGHT1,
    input  wire [ 15:0] WEIGHT0,
    //with sr_tx_fifo
        //多播
    /*(*mark_debug = "true"*)*/ input  wire         sr_tx_fifo_empty_mul ,  //将满标志--预留一个最长帧--深度-24
    /*(*mark_debug = "true"*)*/ output reg          sr_tx_fifo_rden_mul  ,
    /*(*mark_debug = "true"*)*/ input  wire [ 47:0] sr_tx_fifo_rdata_mul ,
        //单播
    /*(*mark_debug = "true"*)*/ input  wire         sr_tx_fifo_empty_7 ,
    /*(*mark_debug = "true"*)*/ output reg          sr_tx_fifo_rden_7  ,
    /*(*mark_debug = "true"*)*/ input  wire [ 47:0] sr_tx_fifo_rdata_7 ,
    input  wire         sr_tx_fifo_empty_6 ,
    output reg          sr_tx_fifo_rden_6  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_6 ,
    input  wire         sr_tx_fifo_empty_5 ,
    output reg          sr_tx_fifo_rden_5  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_5 ,
    input  wire         sr_tx_fifo_empty_4 ,
    output reg          sr_tx_fifo_rden_4  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_4 ,
    input  wire         sr_tx_fifo_empty_3 ,
    output reg          sr_tx_fifo_rden_3  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_3 ,
    input  wire         sr_tx_fifo_empty_2 ,
    output reg          sr_tx_fifo_rden_2  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_2 ,
    input  wire         sr_tx_fifo_empty_1 ,
    output reg          sr_tx_fifo_rden_1  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_1 ,
    input  wire         sr_tx_fifo_empty_0 ,
    output reg          sr_tx_fifo_rden_0  ,
    input  wire [ 47:0] sr_tx_fifo_rdata_0 ,
    //with SRAM_memory
    (*mark_debug = "true"*) output reg  [ 13:0] memory_raddr,
    (*mark_debug = "true"*) output reg          memory_rden ,
    /*(*mark_debug = "true"*)*/ input  wire [255:0] memory_rdata,
    //with crossbar_ctrl_top
    input  wire         uni_tx_rdy0,
    input  wire         uni_tx_rdy1,
    input  wire         uni_tx_rdy2,
    input  wire         uni_tx_rdy3,
    input  wire         mul_tx_rdy0,
    input  wire         mul_tx_rdy1,
    input  wire         mul_tx_rdy2,
    input  wire         mul_tx_rdy3,

    /*(*mark_debug = "true"*)*/ output reg  [255:0] emac_data_in    ,
    /*(*mark_debug = "true"*)*/ output reg          emac_data_wren  ,
    /*(*mark_debug = "true"*)*/ output reg  [  5:0] rx_address_dpram,
    /*(*mark_debug = "true"*)*/ output reg  [  3:0] mac_dest_port_out,
    /*(*mark_debug = "true"*)*/ output wire         mul_indicate_out,
    //with release_addr_fifo
    /*(*mark_debug = "true"*)*/ input  wire         release_addr_fifo_full ,
    /*(*mark_debug = "true"*)*/ output reg          release_addr_fifo_wren ,
    /*(*mark_debug = "true"*)*/ output reg  [ 17:0] release_addr_fifo_wdata  //fisrt_BD+last_BD+BD_addr
    // (*mark_debug = "true"*) input  wire [  6:0] release_addr_fifo_cnt
);
//*******************
//DEFINE LOCAL PARAMETER
//*******************
//parameter(s)
localparam IDLE           = 12'b0000_0000_0000;
localparam START_READ_MUL = 12'b0000_0000_0001;
localparam START_READ_7   = 12'b0000_0000_0010;
localparam START_READ_6   = 12'b0000_0000_0100;
localparam START_READ_5   = 12'b0000_0000_1000;
localparam START_READ_4   = 12'b0000_0001_0000;
localparam START_READ_3   = 12'b0000_0010_0000;
localparam START_READ_2   = 12'b0000_0100_0000;
localparam START_READ_1   = 12'b0000_1000_0000;
localparam START_READ_0   = 12'b0001_0000_0000;
localparam WRITE_JUDGE    = 12'b0010_0000_0000;
localparam WRITE_DPRAM    = 12'b0100_0000_0000;
localparam WRITE_FINISH   = 12'b1000_0000_0000;
//sr_tx_fifo
// _ _ _ 5 _ _  _ _ _ _4 _ _ _ _ _ _ _ _6_ _ _ _  _ _ _ _12 _ _ _ _ _ _11 _ _ _ _ _ _ 7 _ _ _ _ _ _ 1 _ _ _ _ _ 1 _ _
//|    47~43   |     42~39    |       38~33      |     32~20    |    19~ 9     |     8~2      |     1     |     0    |
//|___reserve__|_outport_list_|__dequeue_number__|__BD_address__|_frame_length_|_valid_length_|__first_BD_|__last_BD_|
//交叉节点乒乓RAM写入w256-d64
//6'b000000--队列号-帧长-目的端口列表
//6'b000001--SRAM_memory读出的数据
//*********************
//INNER SIGNAL DECLARATION
//*********************
//REGS
//状态机
// mac_dest_port_in
// dequeue_number  
// frame_length    
// previous_deq_pri
(*mark_debug = "true"*) reg [11:0] c_state,n_state;
//将sr_tx_fifo归一化
(*mark_debug = "true"*) reg [47:0] sr_tx_fifo_out;
//队列号
(*mark_debug = "true"*) reg [ 5:0] dequeue_number;
(*mark_debug = "true"*) reg [ 5:0] dequeue_number_reg;
//dequeue_pri in previous shedule
// (*mark_debug = "true"*) reg [ 2:0] previous_deq_pri;
// (*mark_debug = "true"*) reg [ 2:0] previous_deq_pri_reg;
//帧长
(*mark_debug = "true"*) reg [10:0] frame_length;
(*mark_debug = "true"*) reg [10:0] frame_length_reg;
(*mark_debug = "true"*) reg [ 3:0] mac_dest_port_in ;
(*mark_debug = "true"*) reg [ 3:0] mac_dest_port_in_reg;
(*mark_debug = "true"*) reg [ 3:0] mac_dest_port_in_reg_dl;
// reg [11:0] BD_address;
// reg [ 6:0] valid_length;
// reg        first_BD;
// reg        last_BD;
//一帧读完结束标志
// reg        last_frame;

//处于WRITE_DPRAM状态的延迟计数
(*mark_debug = "true"*) reg [ 3:0] read_ram_step;
reg [ 3:0] read_ram_step_dl;
// (*mark_debug = "true"*) reg [ 3:0] write_dpram_step;

//读帧尾
// reg [ 1:0] read_tail_delay;
//新增DWRR调度算法相关信号
reg [ 7:0] weight;
reg [15:0] weight_back;
reg [15:0] length_pri_7,length_pri_6,length_pri_5,length_pri_4;
reg [15:0] length_pri_3,length_pri_2,length_pri_1,length_pri_0;

reg        frame_writing; //写dpram
reg        frame_reading_dl;
reg        mul_indicate_dl3;
reg        mul_indicate_dl2;
reg        mul_indicate_dl;
reg        mul_indicate;

// sr_tx_fifo打拍采样
reg [47:0] sr_tx_fifo_rdata_mul_reg;
reg [47:0] sr_tx_fifo_rdata_0_reg;
reg [47:0] sr_tx_fifo_rdata_1_reg;
reg [47:0] sr_tx_fifo_rdata_2_reg;
reg [47:0] sr_tx_fifo_rdata_3_reg;
reg [47:0] sr_tx_fifo_rdata_4_reg;
reg [47:0] sr_tx_fifo_rdata_5_reg;
reg [47:0] sr_tx_fifo_rdata_6_reg;
reg [47:0] sr_tx_fifo_rdata_7_reg;

reg        sr_tx_fifo_empty_mul_reg;
reg        sr_tx_fifo_empty_0_reg;
reg        sr_tx_fifo_empty_1_reg;
reg        sr_tx_fifo_empty_2_reg;
reg        sr_tx_fifo_empty_3_reg;
reg        sr_tx_fifo_empty_4_reg;
reg        sr_tx_fifo_empty_5_reg;
reg        sr_tx_fifo_empty_6_reg;
reg        sr_tx_fifo_empty_7_reg;

//帧ram采样
reg [255:0] memory_rdata_reg;

//WIRES
//目的端口匹配--转发目的端口准备好
wire uni_port0_match,uni_port1_match;
wire uni_port2_match,uni_port3_match;
wire mul_port0_match,mul_port1_match;
wire mul_port2_match,mul_port3_match;

//sr_tx_fifo信息
wire [7:0]  sr_tx_fifo_empty;
// wire        wight_update;

wire        write_dpram_rdy;
wire [11:0] BD_address;
wire [ 6:0] valid_length;
wire        first_BD;
wire        last_BD;
//一帧读完结束标志
wire        last_frame;
//*********************
//INSTANTCE MODULE
//*********************

//*********************
//MAIN CORE
//********************* 
reg DWRR_en_ff1;
wire DWRR_en_pos;
assign sr_tx_fifo_empty = {sr_tx_fifo_empty_7_reg,sr_tx_fifo_empty_6_reg,sr_tx_fifo_empty_5_reg,sr_tx_fifo_empty_4_reg,sr_tx_fifo_empty_3_reg,sr_tx_fifo_empty_2_reg,sr_tx_fifo_empty_1_reg,sr_tx_fifo_empty_0_reg};
// assign wight_update = ~(|((~sr_tx_fifo_empty) & weight));
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        weight_back <= 16'b0;
    end
    else if ((c_state == IDLE) && (release_addr_fifo_full == 1'b0) && (sr_tx_fifo_empty_mul == 1'b1) && (&sr_tx_fifo_empty == 1'b0)) begin
        if(weight_back == weight_back_num) begin
            weight_back <= 16'b0;
        end
        else begin
            weight_back <= weight_back + 16'b1;
        end      
    end
    else begin
        weight_back <= 16'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        DWRR_en_ff1 <= 1'b0;
    end
    else begin
       DWRR_en_ff1 <= DWRR_en;
    end
end
assign DWRR_en_pos = DWRR_en & (~DWRR_en_ff1);

//权重按字节计数
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_7 <= 16'd0;
    end
    else if (c_state == START_READ_7) begin
        if (length_pri_7 >= {5'b0,frame_length}) begin
            length_pri_7 <= length_pri_7 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[6:0]}) & (previous_deq_pri == 3'd7)) begin
        //     length_pri_7 <= WEIGHT7[15:0];
        // end
        else begin
            length_pri_7 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[6:0]}) & (previous_deq_pri == 3'd7)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_7 <= WEIGHT7[15:0];
    end     
    else begin
        length_pri_7 <= length_pri_7;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_6 <= 16'd0;
    end 
    else if (c_state == START_READ_6) begin
        if (length_pri_6 >= {5'b0,frame_length}) begin
            length_pri_6 <= length_pri_6 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7],sr_tx_fifo_empty[5:0]}) & (previous_deq_pri == 3'd6)) begin
        //     length_pri_6 <= WEIGHT6[15:0];
        // end
        else begin
            length_pri_6 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7],sr_tx_fifo_empty[5:0]}) & (previous_deq_pri == 3'd6)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_6 <= WEIGHT6[15:0];
    end   
    else begin
        length_pri_6 <= length_pri_6;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_5 <= 16'd0;
    end  
    else if (c_state == START_READ_5) begin
        if (length_pri_5 >= {5'b0,frame_length}) begin
            length_pri_5 <= length_pri_5 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:6],sr_tx_fifo_empty[4:0]}) & (previous_deq_pri == 3'd5)) begin
        //     length_pri_5 <= WEIGHT5[15:0];
        // end
        else begin
            length_pri_5 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:6],sr_tx_fifo_empty[4:0]}) & (previous_deq_pri == 3'd5)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_5 <= WEIGHT5[15:0];
    end    
    else begin
        length_pri_5 <= length_pri_5;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_4 <= 16'd0;
    end
    else if (c_state == START_READ_4) begin
        if (length_pri_4 >= {5'b0,frame_length}) begin
            length_pri_4 <= length_pri_4 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:5],sr_tx_fifo_empty[3:0]}) & (previous_deq_pri == 3'd4)) begin
        //     length_pri_4 <= WEIGHT4[15:0];
        // end
        else begin
            length_pri_4 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:5],sr_tx_fifo_empty[3:0]}) & (previous_deq_pri == 3'd4)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_4 <= WEIGHT4[15:0];
    end    
    else begin
        length_pri_4 <= length_pri_4;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_3 <= 16'd0;
    end  
    else if (c_state == START_READ_3) begin
        if (length_pri_3 >= {5'b0,frame_length}) begin
            length_pri_3 <= length_pri_3 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:4],sr_tx_fifo_empty[2:0]}) & (previous_deq_pri == 3'd3)) begin
        //     length_pri_3 <= WEIGHT3[15:0];
        // end
        else begin
            length_pri_3 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:4],sr_tx_fifo_empty[2:0]}) & (previous_deq_pri == 3'd3)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_3 <= WEIGHT3[15:0];
    end  
    else begin
        length_pri_3 <= length_pri_3;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_2 <= 16'd0;
    end
    else if (c_state == START_READ_2) begin
        if (length_pri_2 >= {5'b0,frame_length}) begin
            length_pri_2 <= length_pri_2 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:3],sr_tx_fifo_empty[1:0]}) & (previous_deq_pri == 3'd2)) begin
        //     length_pri_2 <= WEIGHT2[15:0];
        // end
        else begin
            length_pri_2 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:3],sr_tx_fifo_empty[1:0]}) & (previous_deq_pri == 3'd2)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_2 <= WEIGHT2[15:0];
    end    
    else begin
        length_pri_2 <= length_pri_2;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_1 <= 16'd0;
    end
    else if (c_state == START_READ_1) begin
        if (length_pri_1 >= {5'b0,frame_length}) begin
            length_pri_1 <= length_pri_1 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:2],sr_tx_fifo_empty[0]}) & (previous_deq_pri == 3'd1)) begin
        //     length_pri_1 <= WEIGHT1[15:0];
        // end
        else begin
            length_pri_1 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:2],sr_tx_fifo_empty[0]}) & (previous_deq_pri == 3'd1)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_1 <= WEIGHT1[15:0];
    end    
    else begin
        length_pri_1 <= length_pri_1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        length_pri_0 <= 16'd0;
    end
    else if (c_state == START_READ_0) begin
        if (length_pri_0 >= {5'b0,frame_length}) begin
            length_pri_0 <= length_pri_0 - frame_length;
        end
        // else if((&{sr_tx_fifo_empty[7:1]}) & (previous_deq_pri == 3'd0)) begin
        //     length_pri_0 <= WEIGHT0[15:0];
        // end
        else begin
            length_pri_0 <= 16'd0;
        end
    end
    // else if((&{sr_tx_fifo_empty[7:1]}) & (previous_deq_pri == 3'd0)) begin
    else if ((weight == 8'b0000_0000) || (weight_back == weight_back_num)) begin
        length_pri_0 <= WEIGHT0[15:0];
    end
    else begin
        length_pri_0 <= length_pri_0;
    end
end

//权重有效
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        weight <= 8'b1111_1111;
    end
    else if (DWRR_en == 1'b0) begin  //未开启DWRR使能,按照SP调度
        weight <= 8'b1111_1111;
    end
    else /*if(c_state == WRITE_DPRAM) */begin
        weight[7] <= (|length_pri_7);
        weight[6] <= (|length_pri_6);
        weight[5] <= (|length_pri_5);
        weight[4] <= (|length_pri_4);
        weight[3] <= (|length_pri_3);
        weight[2] <= (|length_pri_2);
        weight[1] <= (|length_pri_1);
        weight[0] <= (|length_pri_0);
    end
    // else if ((n_state == START_READ_7) && (length_pri_7 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[7] <= 1'b0;
    // end
    // else if ((n_state == START_READ_6) && (length_pri_6 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[6] <= 1'b0;
    // end
    // else if ((n_state == START_READ_5) && (length_pri_5 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[5] <= 1'b0;
    // end
    // else if ((n_state == START_READ_4) && (length_pri_4 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[4] <= 1'b0;
    // end
    // else if ((n_state == START_READ_3) && (length_pri_3 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[3] <= 1'b0;
    // end
    // else if ((n_state == START_READ_2) && (length_pri_2 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[2] <= 1'b0;
    // end
    // else if ((n_state == START_READ_1) && (length_pri_1 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[1] <= 1'b0;
    // end
    // else if ((n_state == START_READ_0) && (length_pri_0 == 16'd0)) begin  //开启DWRR使能,为DWRR调度
    //     weight[0] <= 1'b0;
    // end
    // else if (weight == 8'b0000_0000) begin
    //     weight <= 8'b1111_1111;
    // end
    // else begin
    //     weight <= weight;
    // end
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        sr_tx_fifo_rdata_mul_reg <=  48'b0 ;
        sr_tx_fifo_rdata_0_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_1_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_2_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_3_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_4_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_5_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_6_reg   <=  48'b0 ;
        sr_tx_fifo_rdata_7_reg   <=  48'b0 ;
    end
    else begin
        sr_tx_fifo_rdata_mul_reg <=  sr_tx_fifo_rdata_mul ;
        sr_tx_fifo_rdata_0_reg   <=  sr_tx_fifo_rdata_0   ;
        sr_tx_fifo_rdata_1_reg   <=  sr_tx_fifo_rdata_1   ;
        sr_tx_fifo_rdata_2_reg   <=  sr_tx_fifo_rdata_2   ;
        sr_tx_fifo_rdata_3_reg   <=  sr_tx_fifo_rdata_3   ;
        sr_tx_fifo_rdata_4_reg   <=  sr_tx_fifo_rdata_4   ;
        sr_tx_fifo_rdata_5_reg   <=  sr_tx_fifo_rdata_5   ;
        sr_tx_fifo_rdata_6_reg   <=  sr_tx_fifo_rdata_6   ;
        sr_tx_fifo_rdata_7_reg   <=  sr_tx_fifo_rdata_7   ;        
    end
end
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_empty_mul_reg <=  1'b1 ;
        sr_tx_fifo_empty_0_reg   <=  1'b1 ;
        sr_tx_fifo_empty_1_reg   <=  1'b1 ;
        sr_tx_fifo_empty_2_reg   <=  1'b1 ;
        sr_tx_fifo_empty_3_reg   <=  1'b1 ;
        sr_tx_fifo_empty_4_reg   <=  1'b1 ;
        sr_tx_fifo_empty_5_reg   <=  1'b1 ;
        sr_tx_fifo_empty_6_reg   <=  1'b1 ;
        sr_tx_fifo_empty_7_reg   <=  1'b1 ;        
    end
    else begin
        sr_tx_fifo_empty_mul_reg <=  sr_tx_fifo_empty_mul ;
        sr_tx_fifo_empty_0_reg   <=  sr_tx_fifo_empty_0   ;
        sr_tx_fifo_empty_1_reg   <=  sr_tx_fifo_empty_1   ;
        sr_tx_fifo_empty_2_reg   <=  sr_tx_fifo_empty_2   ;
        sr_tx_fifo_empty_3_reg   <=  sr_tx_fifo_empty_3   ;
        sr_tx_fifo_empty_4_reg   <=  sr_tx_fifo_empty_4   ;
        sr_tx_fifo_empty_5_reg   <=  sr_tx_fifo_empty_5   ;
        sr_tx_fifo_empty_6_reg   <=  sr_tx_fifo_empty_6   ;
        sr_tx_fifo_empty_7_reg   <=  sr_tx_fifo_empty_7   ;        
    end
end
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        memory_rdata_reg <= 256'b0;
    end
    else begin
        memory_rdata_reg <= memory_rdata;        
    end
end

//端口匹配
//  //单播
assign uni_port0_match = mac_dest_port_in[0] ? uni_tx_rdy0 : 1'b1 ;
assign uni_port1_match = mac_dest_port_in[1] ? uni_tx_rdy1 : 1'b1 ;
assign uni_port2_match = mac_dest_port_in[2] ? uni_tx_rdy2 : 1'b1 ;
assign uni_port3_match = mac_dest_port_in[3] ? uni_tx_rdy3 : 1'b1 ;
//  //多播
assign mul_port0_match = mac_dest_port_in[0] ? mul_tx_rdy0 : 1'b1 ;
assign mul_port1_match = mac_dest_port_in[1] ? mul_tx_rdy1 : 1'b1 ;
assign mul_port2_match = mac_dest_port_in[2] ? mul_tx_rdy2 : 1'b1 ;
assign mul_port3_match = mac_dest_port_in[3] ? mul_tx_rdy3 : 1'b1 ;

assign write_dpram_rdy = ((mul_indicate == 1'b1) && (mul_port0_match == 1'b1) && (mul_port1_match == 1'b1) && (mul_port2_match == 1'b1) && (mul_port3_match == 1'b1)) 
                            || ((mul_indicate == 1'b0) && (uni_port0_match == 1'b1) && (uni_port1_match == 1'b1) && (uni_port2_match == 1'b1) && (uni_port3_match == 1'b1));

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        c_state <= IDLE;
    end
    else begin
        c_state <= n_state;
    end
end

always @(*) begin
    case(c_state)
        IDLE:
        begin
            if ((sr_tx_fifo_empty_mul == 1'b0) /*&& (sr_tx_fifo_empty_mul_reg == 1'b0)*/ && (release_addr_fifo_full == 1'b0) /*&& (release_addr_fifo_cnt <= 7'd103)*/) begin  //释放地址FIFO将满标志可以存放一个最长帧
                n_state = START_READ_MUL;
            end
            else if ((sr_tx_fifo_empty_7 == 1'b0) /*&& (sr_tx_fifo_empty_7_reg == 1'b0)*/ && (weight[7] == 1'b1)) begin
                n_state = START_READ_7;
            end
            else if ((sr_tx_fifo_empty_6 == 1'b0) /*&& (sr_tx_fifo_empty_6_reg == 1'b0)*/ && (weight[6] == 1'b1)) begin
                n_state = START_READ_6;
            end
            else if ((sr_tx_fifo_empty_5 == 1'b0) /*&& (sr_tx_fifo_empty_5_reg == 1'b0)*/ && (weight[5] == 1'b1)) begin
                n_state = START_READ_5;
            end
            else if ((sr_tx_fifo_empty_4 == 1'b0) /*&& (sr_tx_fifo_empty_4_reg == 1'b0)*/ && (weight[4] == 1'b1)) begin
                n_state = START_READ_4;
            end
            else if ((sr_tx_fifo_empty_3 == 1'b0) /*&& (sr_tx_fifo_empty_3_reg == 1'b0)*/ && (weight[3] == 1'b1)) begin
                n_state = START_READ_3;
            end
            else if ((sr_tx_fifo_empty_2 == 1'b0) /*&& (sr_tx_fifo_empty_2_reg == 1'b0)*/ && (weight[2] == 1'b1)) begin
                n_state = START_READ_2;
            end
            else if ((sr_tx_fifo_empty_1 == 1'b0) /*&& (sr_tx_fifo_empty_1_reg == 1'b0)*/ && (weight[1] == 1'b1)) begin
                n_state = START_READ_1;
            end
            else if ((sr_tx_fifo_empty_0 == 1'b0) /*&& (sr_tx_fifo_empty_0_reg == 1'b0)*/ && (weight[0] == 1'b1)) begin
                n_state = START_READ_0;
            end
            else begin
                n_state = IDLE;
            end
        end
        START_READ_MUL:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_MUL;
            end
        end
        START_READ_7:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_7;
            end
        end
        START_READ_6:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_6;
            end
        end
        START_READ_5:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_5;
            end
        end
        START_READ_4:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_4;
            end
        end
        START_READ_3:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_3;
            end
        end
        START_READ_2:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_2;
            end
        end
        START_READ_1:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_1;
            end
        end
        START_READ_0:
        begin
            if (write_dpram_rdy) begin
                n_state = WRITE_DPRAM;
            end
            else begin
                n_state = START_READ_0;
            end
        end
        WRITE_DPRAM:
        begin
            if(last_frame) begin
                if(valid_length[6:5] == 2'd0) begin
                    n_state = WRITE_FINISH;
                end
                else begin
                    n_state = IDLE;
                end
            end
            else begin
                n_state = WRITE_DPRAM;
            end
        end
        WRITE_FINISH:
            n_state = IDLE;
        default:
        begin
            n_state = IDLE;
        end
    endcase
end

//单多播标识
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        mul_indicate <= 1'b0;
    end
    else if (c_state == START_READ_MUL) begin
        mul_indicate <= 1'b1;
    end
    else if (c_state == IDLE) begin
        mul_indicate <= 1'b0;
    end
    else begin
        mul_indicate <= mul_indicate;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        mul_indicate_dl     	<= 1'b0;
        mul_indicate_dl2    	<= 1'b0;
        mul_indicate_dl3    	<= 1'b0;
	mac_dest_port_in_reg_dl <= 4'b0;
	mac_dest_port_out	<= 4'b0;
    end
    else begin
        mul_indicate_dl     	<= mul_indicate     		;
        mul_indicate_dl2    	<= mul_indicate_dl   		;
        mul_indicate_dl3    	<= mul_indicate_dl2  		;
	mac_dest_port_in_reg_dl <= mac_dest_port_in_reg 	;
	mac_dest_port_out 	<= mac_dest_port_in_reg_dl 	;
    end
end
assign mul_indicate_out = /*mul_indicate_dl2 ||*/ mul_indicate_dl3;

//目的端口列表--优先级
always @(*) begin
    case(c_state)
        START_READ_MUL:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_mul_reg[42:39] ;
            dequeue_number   = sr_tx_fifo_rdata_mul_reg[38:33] ;
            frame_length     = sr_tx_fifo_rdata_mul_reg[19: 9] ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_7:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_7_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_7_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_7_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_6:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_6_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_6_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_6_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]         ;
        end
        START_READ_5:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_5_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_5_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_5_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]         ;
        end
        START_READ_4:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_4_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_4_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_4_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_3:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_3_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_3_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_3_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_2:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_2_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_2_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_2_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_1:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_1_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_1_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_1_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        START_READ_0:
        begin
            mac_dest_port_in = sr_tx_fifo_rdata_0_reg[42:39]   ;
            dequeue_number   = sr_tx_fifo_rdata_0_reg[38:33]   ;
            frame_length     = sr_tx_fifo_rdata_0_reg[19: 9]   ;
            // previous_deq_pri = dequeue_number_reg[2:0]          ;
        end
        default:
        begin
            mac_dest_port_in = 'd0;
            dequeue_number   = 'd0;
            frame_length     = 'd0;
            // previous_deq_pri = 'd0;
        end
    endcase 
end


always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        mac_dest_port_in_reg    <= 4'd0   ;
        dequeue_number_reg      <= 6'b0   ;
        frame_length_reg        <= 11'b0  ;
        // previous_deq_pri_reg <= 3'b0   ;
    end
    else if((c_state == START_READ_MUL) || (c_state == START_READ_7) ||
        (c_state == START_READ_6) || (c_state == START_READ_5) || 
        (c_state == START_READ_4) || (c_state == START_READ_4) ||
        (c_state == START_READ_3) || (c_state == START_READ_2) ||
        (c_state == START_READ_1) || (c_state == START_READ_0)) begin
        mac_dest_port_in_reg    <= mac_dest_port_in ;
        dequeue_number_reg      <= dequeue_number   ;
        frame_length_reg        <= frame_length     ;
        // previous_deq_pri_reg    <= previous_deq_pri ;
    end
    else begin
    mac_dest_port_in_reg    <= mac_dest_port_in_reg ;
    dequeue_number_reg      <= dequeue_number_reg   ;
    frame_length_reg        <= frame_length_reg     ;
    // previous_deq_pri_reg    <= previous_deq_pri_reg ;
    end
end

//sr_tx_fifo归一
always @(*) begin
    if (mul_indicate == 1'b1) begin
        sr_tx_fifo_out = sr_tx_fifo_rdata_mul_reg;
    end
    else begin
    case(dequeue_number_reg[2:0])
        3'b000 : sr_tx_fifo_out = sr_tx_fifo_rdata_0_reg;
        3'b001 : sr_tx_fifo_out = sr_tx_fifo_rdata_1_reg;
        3'b010 : sr_tx_fifo_out = sr_tx_fifo_rdata_2_reg;
        3'b011 : sr_tx_fifo_out = sr_tx_fifo_rdata_3_reg;
        3'b100 : sr_tx_fifo_out = sr_tx_fifo_rdata_4_reg;
        3'b101 : sr_tx_fifo_out = sr_tx_fifo_rdata_5_reg;
        3'b110 : sr_tx_fifo_out = sr_tx_fifo_rdata_6_reg;
        3'b111 : sr_tx_fifo_out = sr_tx_fifo_rdata_7_reg;
        default: sr_tx_fifo_out = 48'd0;
    endcase
    end
end

assign BD_address       = sr_tx_fifo_out[31:20];
assign valid_length     = sr_tx_fifo_out[ 8: 2];
assign first_BD         = sr_tx_fifo_out[1];
assign last_BD          = sr_tx_fifo_out[0];

assign last_frame = (c_state == WRITE_DPRAM) && last_BD && (read_ram_step[1:0] == valid_length[6:5]);

// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n) begin
//         last_frame <= 1'd0; 
//     end
//     else if ((c_state == WRITE_DPRAM) && last_BD && (read_ram_step[1:0] == valid_length[6:5])) begin
//         last_frame <= 1'b1;
//     end
//     else begin
//         last_frame <= 1'b0;
//     end
// end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        frame_reading_dl <= 1'd0; 
    end
    // else if (c_state == WRITE_DPRAM) begin
    //     frame_reading_dl <= 1'b1;
    // end
    else begin
        frame_reading_dl <= memory_rden;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        frame_writing <= 1'd0; 
    end
    else begin
        frame_writing <= frame_reading_dl;
    end
end

//处于WRITE_DPRAM状态的延迟计数

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
       read_ram_step <= 3'd0; 
    end
    else if (c_state == WRITE_DPRAM) begin
        if (read_ram_step == 3'd3) begin  
            read_ram_step <= 3'd0;
        end
        else begin
            read_ram_step <= read_ram_step + 3'd1;
        end
    end
    else begin
        read_ram_step <= 3'd0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
       // write_dpram_step <= 3'd0; 
       read_ram_step_dl <= 3'd0;
    end
    else begin
       read_ram_step_dl <= read_ram_step;
       // write_dpram_11111step <= read_ram_step_dl;
    end
end


//拉高片内换存读使能地址
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        memory_rden  <= 1'b0;
        memory_raddr <= 14'd0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0)) begin
        memory_rden  <= 1'b1;
        memory_raddr <= {BD_address,2'b0};
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step != 3'd0)) begin
        memory_rden  <= 1'b1;
        memory_raddr <= memory_raddr + 14'b1;
    end
    else begin
        memory_rden  <= 1'b0;
        memory_raddr <= 14'd0;
    end
end

//释放BD地址
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        release_addr_fifo_wren  <= 1'b0;
        release_addr_fifo_wdata <= 18'd0; 
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 2'd0)) begin
        release_addr_fifo_wren  <= 1'b1;
        release_addr_fifo_wdata <= {first_BD,last_BD,4'd0,BD_address};
    end
    else begin
        release_addr_fifo_wren  <= 1'b0;
        release_addr_fifo_wdata <= 18'd0;
    end
end

//将数据写入交叉节点乒乓RAM中

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        emac_data_in     <= 256'd0;
        emac_data_wren   <= 1'b0;
        rx_address_dpram <= 6'd0;
    end
    else if ((|read_ram_step_dl) && (~frame_writing)) begin  //写第0行，信息
        emac_data_in     <= {235'd0,dequeue_number_reg,frame_length_reg,mac_dest_port_in_reg};
        emac_data_wren   <= 1'b1;
        rx_address_dpram <= 6'd0;
    end
    else if (frame_writing) begin
        emac_data_in     <= memory_rdata_reg;
        emac_data_wren   <= 1'b1;
        rx_address_dpram <= rx_address_dpram + 6'd1;
    end
    else begin
        emac_data_in     <= 256'd0;
        emac_data_wren   <= 1'b0;
        rx_address_dpram <= 6'd0;
    end
end

// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n) begin
//         mac_dest_port_in_reg <= 4'b0;
//     end
//     else if ((|read_ram_step_dl) && (~frame_writing)) begin  //写第0行，信息
//         mac_dest_port_in_reg <= mac_dest_port_in;
//     end
//     else begin
//         mac_dest_port_in_reg <= mac_dest_port_in_reg;
//     end
// end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_mul <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b1) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_mul <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b1) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_mul <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_mul <= 1'b0;
    end
end

//  //单播
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_7 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b111) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_7 <= 1'b1;
    end    
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b111) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_7 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_7 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_6 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b110) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_6 <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b110) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_6 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_6 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_5 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b101) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_5 <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b101) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_5 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_5 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_4 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b100) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_4 <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b100) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_4 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_4 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_3 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b011) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_3 <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b011) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_3 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_3 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_2 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b010) && (valid_length[6] == 1'd1)) begin
        sr_tx_fifo_rden_2 <= 1'b1;
    end    
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b010) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_2 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_2 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_1 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (valid_length[6] == 1'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b001)) begin
        sr_tx_fifo_rden_1 <= 1'b1;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b001) && (valid_length[6] == 1'd0)) begin
        sr_tx_fifo_rden_1 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_1 <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        sr_tx_fifo_rden_0 <= 1'b0;
    end
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd1) && (valid_length[6] == 1'd1) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b000)) begin
        sr_tx_fifo_rden_0 <= 1'b1;
    end    
    else if ((c_state == WRITE_DPRAM) && (read_ram_step == 3'd0) && (valid_length[6] == 1'd0) && (mul_indicate == 1'b0) && (dequeue_number_reg[2:0] == 3'b000)) begin
        sr_tx_fifo_rden_0 <= 1'b1;
    end
    else begin
        sr_tx_fifo_rden_0 <= 1'b0;
    end
end
// mark_debug ------------- release_addr

(*mark_debug = "true"*) reg [11:0]  release_BD_addr_dl;
(*mark_debug = "true"*) reg         release_BD_error;
 always @(posedge clk or negedge rst_n) begin : get_previous_BD
     if (~rst_n) begin
         // reset
         release_BD_addr_dl <= 12'b1;
     end
     else if(release_addr_fifo_wren) begin
        if(release_addr_fifo_wdata[11:0] == `BDNUM) begin
            release_BD_addr_dl <= 12'd1;
        end
        else begin
           release_BD_addr_dl <= release_addr_fifo_wdata[11:0]  + 12'd1; 
        end
     end
     else begin
         release_BD_addr_dl <= release_BD_addr_dl;
     end
 end

always @(posedge clk or negedge rst_n) begin : compare_BD_address
     if (~rst_n) begin
         // reset
         release_BD_error <= 1'b0;
     end
     else if(release_addr_fifo_wren) begin
         if(release_BD_addr_dl != release_addr_fifo_wdata[11:0]) begin
             release_BD_error <= 1'b1;
         end
         else begin
             release_BD_error <= 1'b0;
         end
     end
     else begin
         release_BD_error <= 1'b0;
     end
 end

// mark_debug
//(*mark_debug = "true"*) reg [31:0] bus_tx_cnt;
//always @(posedge clk or negedge rst_n) begin
//    if (~rst_n) begin
//        bus_tx_cnt <= 32'd0;
//    end
//    else if (c_state == WRITE_DPRAM && n_state != WRITE_DPRAM) begin
//        bus_tx_cnt <= bus_tx_cnt + 1'b1;
//    end
//    else begin
//        bus_tx_cnt <= bus_tx_cnt;
//    end
//end


// `ifdef SIM 
// integer dequeue_data;
// initial
// begin
//     dequeue_data = $fopen("dequeue_data.txt");
// end

// always @(posedge clk) begin
//     if ((emac_data_wren) && (rx_address_dpram != 6'd0)) begin
//         $fwrite(dequeue_data,"%h\n",emac_data_in);
//     end
// end

// initial
// begin
//     wait(bus_tx_cnt == `SEND_NUM && c_state == IDLE)
//         $fclose(dequeue_data);
// end
// `endif

endmodule
